package com.dzsw.thread;


public class WaitMain {

    public static void main(String[] args) throws Exception {
        test2();
    }

    public static void test1() throws Exception {
        final Shared shared = new Shared();
        Thread t1 = new Thread(shared::waitMethod);
        t1.start();
        Thread t2 = new Thread(shared::waitMethod);
        t2.start();

        Thread.sleep(3 * 1000);
        Thread t3 = new Thread(shared::notifyAllThread);
        t3.start();
    }

    public static void test2() throws Exception {
        final Shared1 shared1 = new Shared1();
        Thread t1 = new Thread(shared1::waitMethod);
        t1.start();
        Thread t2 = new Thread(shared1::waitMethod);
        t2.start();

        Thread.sleep(3 * 1000);
        Thread t3 = new Thread(shared1::notifyAllThread);
        t3.start();
    }
}


class Shared {
    synchronized void waitMethod() {
        Thread t = Thread.currentThread();
        System.out.println(t.getName() + " is releasing the lock and going to wait");
        try {
            this.wait();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(t.getName() + " has been notified and acquired the lock back");
    }

    synchronized void notifyOneThread() {
        Thread t = Thread.currentThread();
        this.notify();
        System.out.println(t.getName() + " has notified one thread waiting for this object lock");
    }

    synchronized void notifyAllThread() {
        Thread t = Thread.currentThread();
        this.notifyAll();
        System.out.println(t.getName() + " has notified one thread waiting for this object lock");
    }
}

class Shared1 {

    private final Object obj = new Object();

    public Shared1() {

    }

    public void waitMethod() {
        synchronized(obj) {
            Thread t = Thread.currentThread();
            System.out.println(t.getName() + " is releasing the lock and going to wait");
            try {
                this.obj.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(t.getName() + " has been notified and acquired the lock back");
        }
    }

    public void notifyOneThread() {
        synchronized(obj) {
            Thread t = Thread.currentThread();
            this.obj.notify();
            System.out.println(t.getName() + " has notified one thread waiting for this object lock");
        }
    }

    public void notifyAllThread() {
        synchronized(obj) {
            Thread t = Thread.currentThread();
            this.obj.notifyAll();
            System.out.println(t.getName() + " has notified one thread waiting for this object lock");
        }
    }
}
